﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace TwainLib
{
    public class TwUtils
    {
        internal static object PtrToTwType(TwType twType, IntPtr handle, TwEntryPointMethods methods)
        {
            switch (twType)
            {
                case TwType.Bool:
                    return (handle != IntPtr.Zero);
                case TwType.Fix32:
                    TwFix32 fix32 = new TwFix32();
                    fix32.FromInt(handle.ToInt32());
                    return fix32.ToFloat();
                case TwType.Frame:
                    TwFrame frame = new TwFrame();
                    frame.FromPtr(handle, methods);
                    return frame;
                case TwType.Int8:
                    return (byte)handle;
                case TwType.Int16:
                    return (short)handle;
                case TwType.Int32:
                    return (int)handle;
                case TwType.UInt8:
                case TwType.UInt16:
                case TwType.UInt32:
                    return (uint)handle;
            }
            return null;
        }

        internal static object ReadFromMem(IntPtr baseAddr, int offset, TwType twType)
        {
            switch (twType)
            {
                case TwType.Int8:
                case TwType.UInt8:
                    return Marshal.ReadByte(baseAddr, offset);
                case TwType.Int16:
                    return Marshal.ReadInt16(baseAddr, offset);
                case TwType.Int32:
                    return Marshal.ReadInt32(baseAddr, offset);
                case TwType.UInt16:
                    return (ushort)Marshal.ReadInt16(baseAddr, offset);
                case TwType.UInt32:
                    return (uint)Marshal.ReadInt32(baseAddr, offset);
                case TwType.Bool:
                    return (Marshal.ReadInt16(baseAddr, offset) == 0);
                case TwType.Fix32:
                    TwFix32 fix32 = new TwFix32();
                    fix32.FromInt(Marshal.ReadInt32(baseAddr, offset));
                    return fix32.ToFloat();
            }
            return null;
        }

        internal static void WriteToMem(IntPtr baseAddr, int offset, TwType twType, object value)
        {
            switch (twType)
            {
                case TwType.Int8:
                case TwType.UInt8:
                    Marshal.WriteByte(baseAddr, offset, (byte)value);
                    break;
                case TwType.Int16:
                case TwType.UInt16:
                    Marshal.WriteInt16(baseAddr, offset, (short)value);
                    break;
                case TwType.Int32:
                case TwType.UInt32:
                    Marshal.WriteInt32(baseAddr, offset, (int)value);
                    break;
                case TwType.Bool:
                    Marshal.WriteInt16(baseAddr, offset, (short)(((bool)value) ? 1 : 0));
                    break;
                case TwType.Fix32:
                    TwFix32 fix32 = (TwFix32)value;
                    Marshal.WriteInt16(baseAddr, offset, fix32.Whole);
                    Marshal.WriteInt16(baseAddr, offset, (short)fix32.Frac);
                    break;
            }
        }

        internal static int GetTwTypeSize(TwType twType)
        {
            switch (twType)
            {
                case TwType.Bool:
                case TwType.Int16:
                case TwType.UInt16:
                    return 2;
                case TwType.Int8:
                case TwType.UInt8:
                    return 1;
                case TwType.Int32:
                case TwType.UInt32:
                case TwType.Fix32:
                    return 4;
                case TwType.Frame:
                    return 16;
                case TwType.Str32:
                    return 34;
                case TwType.Str64:
                    return 66;
                case TwType.Str128:
                    return 130;
                case TwType.Str255:
                    return 256;
            }
            return 1;
        }
    }
}
